/**
 * 
 */
package menus.flower;

import java.awt.Color;
import java.util.ArrayList;
import java.util.HashSet;

import components.SetupExperiment;
import components.intertitles.BlockInstructions;
import components.intertitles.Trial;
import components.intertitles.TrialInstructions;

import menus.common.AbstractItem;
import menus.common.AbstractMenu;
import menus.common.statemachines.OneStrokeStateMachine;
import menus.flower.recognizers.AbstractFlowerGestureRecognizer;
import menus.flower.recognizers.FlowerGestureRecognizer;
import menus.flower.recognizers.MyFlowerGestureRecognizer;
import menus.flower.recognizers.MyFlowerGestureRecognizer2;
import menus.zone.ZoneMenuStateMachine;
import fr.inria.insitu.noe.Platform;
import fr.lri.swingstates.canvas.CEllipse;
import fr.lri.swingstates.canvas.CShape;
import fr.lri.swingstates.canvas.CStateMachine;
import fr.lri.swingstates.canvas.Canvas;
import fr.lri.swingstates.gestures.Gesture;

/**
 * @author insitu
 *
 */
public class FlowerMenu extends AbstractMenu {

	/*
	 * DONE : permettre de zapper des items
	 */
	
	protected static final int[][] FlowerIndexes = {
		{0, 8, 16, 1, 9, 2, 10, 18 ,26, 3, 4, 12, 20, 5, 14, 22},
		{0, 8, 16, 1, 9, 2, 10, 18 ,26, 3, 4, 12, 20, 5, 14, 22, 24, 17, 34, 11, 28, 13, 30, 7},
		{0, 8, 16, 1, 9, 2, 10, 18 ,26, 3, 4, 12, 20, 5, 14, 22, 24, 17, 34, 11, 28, 13, 30, 7, 32, 25, 42, 19, 36, 21, 6, 15}
	};
	
	protected FlowerMenuStateMachine stateMachine;
	
	/**
	 * Used for the experiment
	 */
	protected int selectedIndex;
	
	
	
	/**
	 * @param canvas
	 * @param itemLabels
	 */
	public FlowerMenu(Canvas canvas, String[][] itemLabels) {
		
		super(canvas, itemLabels);
		
		stateMachine = new FlowerMenuStateMachine(canvas, this);
		
		HashSet<Integer> availableItemIDs = new HashSet<Integer>(56);
		for(int i = 0; i < itemLabels.length; i++){
			for (int j = 0; j < itemLabels[i].length; j++){
				if(itemLabels[i][j] != null){
					availableItemIDs.add(getIndex(i, j));
				}
			}
		}
		
		analyzer = new MyFlowerGestureRecognizer2(availableItemIDs);
		//((MyFlowerGestureRecognizer)analyzer).extractGestureBase("KppBaseFile.csv");
		((MyFlowerGestureRecognizer2)analyzer).extractGestureBase("AverageGestureData.csv");
		
	}

	@Override
	protected AbstractItem createItem(String[][] itemLabels, int i, int j, String tag) {
		
		return new FlowerMenuItem(this, itemLabels[i][j], getIndex(i, j), i, j, getRotatingDirection(getIndex(i, j)), tag);
		
	}

	@Override
	public AbstractItem getItem(Gesture gesture) {
		
		int selectedItem = ((AbstractFlowerGestureRecognizer)analyzer).recogniseGesture(gesture);
		
		System.out.println("\n\t\tSELECTED : " + selectedItem + "\n");
		
		AbstractItem selected = getItem(selectedItem);
		selectedIndex = ((FlowerMenuItem)selected).index;
		
		return selected;
		
	}
	
	protected AbstractItem getItem(int index){
		
		selectedIndex = index;
		
		return items[getOrientation(index)][getGestureKind(index)];
		
	}
	
	protected static int getOrientation(int index){
		return index%8;
	}
	
	protected static int getGestureKind(int index){
		return index/8;
	}
	
	protected static int getRotatingDirection(int index){
		if (index < 8)
			return 0;
		
		return ( (index/8)%2 == 0 ? -1 : 1 );
	}
	
	public static int getIndex(int orientation, int kind){
		return kind * 8 + orientation;
	}

	
	// ----------------------------------------------------------------------------------
	
	
	@Override
	public boolean isSelectionEnded() {
		return stateMachine.isSelectionEnded();
	}

	@Override
	protected void setLengthError() {
		
		lengthError = 0;
		
	}
	
	@Override
	protected void setPositionError() {
		
		positionError = 0;
		
	}

	@Override
	protected void setOrientationError() {
		
		// Difference between the target item orientation and the selected item orientation
		
		double angleUnit = Math.PI / 4;
		
		orientationError = ( getOrientation(selectedIndex) - getOrientation(targetIndex) ) * angleUnit;
		
		if (orientationError <= -Math.PI){
			orientationError += 2 * Math.PI;
		}
		else if (orientationError >= Math.PI){
			orientationError -= 2 * Math.PI;
		}
		
	}

	@Override
	protected void setShapeError() {
		
		shapeError = getGestureKind(targetIndex) != getGestureKind(selectedIndex);
		
	}

	@Override
	public void resetSelection() {
		stateMachine.resetSelection();
	}

	@Override
	protected void setSelectionDuration() {
		selectionDuration = stateMachine.getSelectionTimes()[1];
	}

	@Override
	protected void setStartTime() {
		startTime = stateMachine.getSelectionTimes()[0];
	}
	
	@Override
	public void drawInstructions(Canvas canvas, CShape zone, String... tags) {
		
		super.drawInstructions(canvas, zone, tags);
		
		CShape stroke = ((FlowerMenuItem)getItem(targetIndex)).createShape(100, 150);
		stroke.translateTo(zone.getCenterX(), zone.getCenterY())
			.setDrawable(true);
		
		canvas.addShape(stroke);
		stroke.addTag(TrialInstructions.InstructionTag);
		
	}
	
	@Override
	public void drawAllInstructions(Canvas canvas, CShape zone, String... tags) {
		
		super.drawInstructions(canvas, zone, tags);
		
		for (int[] items : FlowerIndexes){
			for (int item : items){
				
				CShape stroke = ((FlowerMenuItem)getItem(item)).createShape(100, 250);
				stroke.translateTo(zone.getCenterX(), zone.getCenterY())
					.setDrawable(true);
				
				canvas.addShape(stroke);
				stroke.addTag(TrialInstructions.InstructionTag);
				
			}
		}
		
		CShape stroke = ((FlowerMenuItem)getItem(targetIndex)).createShape(100, 250);
		stroke.setOutlinePaint(Color.green);
		stroke.translateTo(zone.getCenterX(), zone.getCenterY())
			.setDrawable(true);
		
		canvas.addShape(stroke);
		stroke.addTag(TrialInstructions.InstructionTag);
	}
	
	@Override
	public FlowerMenuStateMachine getStateMachine() {
		return stateMachine;
	}
	
	public static void drawMenu() {
		
		Canvas canvas = ((SetupExperiment)Platform.getExperiment().getSetUp()).getGestureArea();
		int[] indexes = FlowerIndexes[(Integer)Platform.getInstance().getFactorValue(Trial.Capacity) / 8 - 2];
		
		for (int itemIndex : indexes){
			
			CShape stroke = FlowerMenuItem.createShape(getGestureKind(itemIndex), getRotatingDirection(itemIndex), getOrientation(itemIndex), 200, 400, "");
			stroke.translateTo(canvas.getCenterX(), canvas.getCenterY())
				.setDrawable(true);
			
			canvas.addShape(stroke);
			
			stroke.addTag(BlockInstructions.InstructionTag);
		}
	}

}
